library(readxl)
library(dplyr)
library(ggplot2)
library(knitr)
library(tidyr)
library(sf)
library(plotly)
data <- read_excel("data.xlsx", sheet = "LFS_Year_2023")
regions <- c(
  "Yerevan",
  "Aragatsotn",
  "Ararat",
  "Armavir",
  "Gegharkunik",
  "Lori",
  "Kotayq",
  "Shirak",
  "Syuniq",
  "Vayoc Dzor",
  "Tavush"
)
people_by_regions <- data %>%
  group_by(A3) %>%
  summarise(
    n = n()
  ) %>%
  mutate(A3 = factor(A3, levels = 1:11, labels = regions)) %>%
  rename(
    region = A3,
    population = n
  )

people_by_regions
ggplot(people_by_regions, aes(x = region, y = population)) +
  geom_col(fill = "plum3") +
  theme_minimal() +
  labs(
    title = "Population by Regions",
    x = "Regions",
    y = "Population"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

urban_rural <- data %>%
  group_by(A5) %>%
  summarise(n = n()) %>%
  mutate(A5 = factor(A5, levels = c(1, 2), labels = c("Urban", "Rural")))

urban_rural
gender_ratio <- data %>%
  group_by(B3) %>%
  summarise(n = n()) %>%
  mutate(B3 = factor(B3, levels = c(1, 2), labels = c("Male", "Female")))

gender_ratio
age_groups <- c(
  "0 - 4",
  "5 - 9",
  "10 - 14",
  "15 - 19",
  "20 - 24",
  "25 - 29",
  "30 - 34",
  "35 - 39",
  "40 - 44",
  "45 - 49",
  "50 - 54",
  "55 - 59",
  "60 - 64",
  "65 - 69",
  "70 - 74",
  "75+"
)
people_by_age <- data %>%
  group_by(Age_16groups) %>%
  summarise(n = n()) %>%
  mutate(Age_16groups = factor(Age_16groups, levels = 1:16, labels = age_groups)) %>%
  rename(
    age_group = Age_16groups,
    population = n
  )

people_by_age
ggplot(people_by_age, aes(x = age_groups, y = population)) +
  geom_col(fill = "plum3") +
  theme_minimal() +
  labs(
    title = "Population by Age Group",
    x = "Age Group",
    y = "Population"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

educational_levels <- c("Illiterate", "No primary", "Primary", "Basic", "Secondary / high", 
                      "Vocational", "Secondary specialized", "Bachelor's degree", 
                      "Master's degree", "Certified specialist", 
                      "Post-graduate (Ph.D, doctorate)")
people_by_education <- data %>%
  group_by(B7) %>%
  summarise(n = n()) %>%
  mutate(B7 = factor(B7, levels = 1:11, labels = educational_levels)) %>%
  rename(
    educational_level = B7,
    population = n
  )

people_by_education
ggplot(people_by_education, aes(x = educational_level, y = population)) +
  geom_col(fill = "plum3") +
  theme_minimal() +
  labs(
    title = "Population by Educational Level",
    x = "Educational Level",
    y = "Population"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

nace_sectors <- c(
  "Agriculture, Forestry and Fishing",
  "Mining and Quarrying",
  "Manufacturing",
  "Electricity, Gas, Steam and Air Conditioning Supply",
  "Water Supply; Sewerage, Waste Management and Remediation Activities",
  "Construction",
  "Wholesale and Retail Trade; Repair of Motor Vehicles and Motorcycles",
  "Transportation and Storage",
  "Accommodation and Food Service Activities",
  "Publishing, Broadcasting, and Content Production and Distribution Activities",
  "Telecommunication, Computer Programming, Consulting, Computing Infrastructure, and other Information Service Activities",
  "Financial and Insurance Activities",
  "Real Estate Activities",
  "Professional, Scientific and Technical Activities",
  "Administrative and Support Service Activities",
  "Public Administration and Defence; Compulsory Social Security",
  "Education",
  "Human Health and Social Work Activities",
  "Arts, Sports and Recreation",
  "Other Service Activities",
  "Activities of Households as Employers; Undifferentiated Goods and Services Producing Activities of Households for Own Use"
)
employees_by_industry <- data %>%
  group_by(E4_21groups_NACE_rev_2.2) %>%
  summarise(n = n()) %>%
  mutate(E4_21groups_NACE_rev_2.2 = factor(E4_21groups_NACE_rev_2.2, levels = 1:21, labels = nace_sectors)) %>%
  rename(
    industry = E4_21groups_NACE_rev_2.2,
    employee_number = n
  )

employees_by_industry
exact_salary_data_points <- data %>%
  select(E14_1) %>%
  na.omit() %>%
  summarise(n = n())

exact_salary_data_points
exact_salary_desc <- data %>%
  select(E14_1) %>%
  na.omit() %>%
  summarise(mean = mean(E14_1), max = max(E14_1), min = min(E14_1), median = median(E14_1))

exact_salary_desc
mean_salary_by_gender <- data %>%
  select(E14_1, B3) %>%
  mutate(B3 = factor(B3, levels = 1:2, labels = c("Male", "Female"))) %>%
  na.omit() %>%
  group_by(B3) %>%
  summarise(mean = mean(E14_1), median = median(E14_1), min = min(E14_1), max = max(E14_1))

mean_salary_by_gender
salary_data <- data %>%
  select(salary = E14_1, gender_code = B3) %>%
  mutate(
    gender = factor(gender_code, levels = c(1, 2), labels = c("Male", "Female"))
  ) %>%
  filter(!is.na(salary), !is.na(gender))

ggplot(salary_data, aes(x = gender, y = salary, fill = gender)) +
  geom_boxplot(outlier.shape = NA) +
  coord_cartesian(ylim = c(0, 500000)) +
  theme_minimal() +
  scale_fill_manual(values = c("Male" = "#56B4E9", "Female" = "#E78AC3")) +
  labs(
    title = "Salary Distribution by Gender",
    x = "Gender",
    y = "Salary"
  ) +
  theme(legend.position = "none")

income_ranges <- c(
  "Up to 55 000 AMD",
  "55 000 AMD",
  "55 001 - 110 000 AMD",
  "110 001 - 220 000 AMD",
  "220 001 - 440 000 AMD",
  "440 001 - 600 000 AMD",
  "600 001 - 700 000 AMD",
  "Refused to answer",
  "Do not know / difficult to answer"
)
categorical_salary_data_points <- data %>%
  select(E15) %>%
  na.omit() %>%
  summarise(number_of_data_points = n())

categorical_salary_data_points
categorical_salary_frequency <- data %>%
  group_by(E15) %>%
  summarise(n = n()) %>%
  na.omit() %>%
  mutate(E15 = factor(E15, levels = 1:9, labels = income_ranges)) %>%
  rename(
    income_range = E15,
    frequency = n
  )

categorical_salary_frequency
ggplot(categorical_salary_frequency, aes(x = income_range, y = frequency)) +
  geom_col(fill = "plum3") +
  theme_minimal() +
  labs(
    title = "Salary Histogram",
    x = "Income Ranges",
    y = "Frequency"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Data Cleaning

checking to see how many rows have more than 50% missing data (from the columns we are going to work on)


cols_to_work <- data[, c('A3', 'A5', 'A6_Month', 'A6_Year', 'B3', 'Age_16groups', 'B7', 'B8', 
                        'B8_Year', 'B9', 'B10', 'B11', 'C1', 'C9', 'C4', 'C3', 'D1', 'D2', 'D3', 'E2_9group', 
                        'E4_21groups_NACE_rev_2.2', 'E5', 'E6', 'E7', 'E9', 'E10', 'E13', 'E14_1', 'E14_2', 'E15', 'E16', 
                        'E17', 'E19', 'E23', 'E24', 'F1', 'F2_9group', 'F3_21groups_NACE_rev_2.2', 'F4', 'F5', 
                        'F6', 'F8_1', 'F8_2', 'G2_1', 'G2_2', 'G2_3Total', 'G3', 'J1_4group', 'J3_1', 'J3_2', 'J3_LastJob')]
missing_per_row <- rowSums(is.na(cols_to_work)) 
total_cols <- length(cols_to_work)
exceeds <- which(missing_per_row > 0.5 * total_cols)
good_rows <-length(exceeds)
print(good_rows)
[1] 16897

check how many empty rows there are

sum(apply(data, 1, function(row) all(is.na(row))))
[1] 0

check how many rows are missing values of important columns

cols_to_check <- c('A3', 'A5', 'A6_Month', 'A6_Year', 'B3', 'Age_16groups', 'B7', 'B8', 
                        'B8_Year', 'B9', 'B10', 'B11', 'C1', 'C9', 'C4', 'C3', 'D1', 'D2', 'D3', 'E2_9group', 
                        'E4_21groups_NACE_rev_2.2', 'E5', 'E6', 'E7', 'E9', 'E10', 'E13', 'E14_1', 'E14_2', 'E15', 'E16', 
                        'E17', 'E19', 'E23', 'E24', 'F1', 'F2_9group', 'F3_21groups_NACE_rev_2.2', 'F4', 'F5', 
                        'F6', 'F8_1', 'F8_2', 'G2_1', 'G2_2', 'G2_3Total', 'G3', 'J1_4group', 'J3_1', 'J3_2', 'J3_LastJob') 
sum(rowSums(is.na(data[cols_to_check])) > 0)
[1] 27007
sum(!is.na(data$E14_2))
[1] 6532
get_mode <- function(x) {
  uniqx <- unique(x)
  uniqx[which.max(tabulate(match(x, uniqx)))]
}
data %>%
  filter(!is.na(E14_2)) %>%
  select(E14_2) %>%
  summarise(mode = get_mode(E14_2))
data %>%
  filter(!is.na(E14_2)) %>%
  count(E14_2, sort = TRUE)

Descriptive Data Analysis and Visualizations

cleaned_data <- read_excel("cleaned_data.xlsx")

Barplot: Counts by Age Range and Gender

Decoding data

decoded_data <- cleaned_data %>%
  mutate(
    B3 = case_when(
      B3 == 1 ~ "Male",
      B3 == 2 ~ "Female",
      TRUE ~ NA_character_
    )
  ) %>%
  mutate(
    Age_16groups = case_when(
      Age_16groups == 1 ~ "0-4",
      Age_16groups == 2 ~ "5-9",
      Age_16groups == 3 ~ "10-14",
      Age_16groups == 4 ~ "15-19",
      Age_16groups == 5 ~ "20-24",
      Age_16groups == 6 ~ "25-29",
      Age_16groups == 7 ~ "30-34",
      Age_16groups == 8 ~ "35-39",
      Age_16groups == 9 ~ "40-44",
      Age_16groups == 10 ~ "45-49",
      Age_16groups == 11 ~ "50-54",
      Age_16groups == 12 ~ "55-59",
      Age_16groups == 13 ~ "60-64",
      Age_16groups == 14 ~ "65-69",
      Age_16groups == 15 ~ "70-74",
      Age_16groups == 16 ~ "75+",
      TRUE ~ NA_character_
    )
  ) %>%
  mutate(
    E15 = case_when(
      E15 == 1 ~ "Up to 55 000 AMD",
      E15 == 2 ~ "55 000 AMD",
      E15 == 3 ~ "55 001 -  110 000 AMD",
      E15 == 4 ~ "110 001 - 220 000 AMD",
      E15 == 5 ~ "220 001 - 440 000 AMD",
      E15 == 6 ~ "440 001 - 600 000 AMD",
      E15 == 7 ~ "600 001 - 700 000 AMD",
      E15 == 8 ~ "Refused to answer",
      E15 == 9 ~ "Do not know / difficult to answer",
      TRUE ~ NA_character_
    )
  ) %>%
  mutate(
    A3 = case_when(
      A3 == 1 ~ "Yerevan",
      A3 == 2 ~ "Aragatsotn",
      A3 == 3 ~ "Ararat",
      A3 == 4 ~ "Armavir",
      A3 == 5 ~ "Gegharkunik",
      A3 == 6 ~ "Lori",
      A3 == 7 ~ "Kotayq",
      A3 == 8 ~ "Shirak",
      A3 == 9 ~ "Syuniq",
      A3 == 10 ~ "Vayoc Dzor",
      A3 == 11 ~ "Tavush",
      TRUE ~ NA_character_
    )
  ) %>%
  mutate(
    A5 = case_when(
      A5 == 1 ~ "Urban",
      A5 == 2 ~ "Rural",
      TRUE ~ NA_character_
    )
  )
ggplot(decoded_data, aes(x = factor(Age_16groups), fill = factor(B3))) +
  geom_bar(position = "stack") + 
  labs(
    title = "Age Distribution by Gender",
    x = "Age Range",
    y = "Count",
    fill = "Gender"
  ) +
  scale_fill_manual(values = c("Male" = "#56B4E9", "Female" = "#E78AC3")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) 

Also, let’s calculate this numerically.

gender_counts <- decoded_data %>%
  group_by(Age_16groups, B3) %>%
  summarise(Count = n(), .groups = "drop")

gender_counts_wide <- gender_counts %>%
  pivot_wider(names_from = B3, values_from = Count, values_fill = 0) %>%
  rename("Age Range" = Age_16groups)

# display
knitr::kable(gender_counts_wide, caption = "Gender Count by Age Group")
Gender Count by Age Group
Age Range Female Male
15-19 29 56
20-24 177 322
25-29 273 576
30-34 418 749
35-39 552 762
40-44 557 626
45-49 492 540
50-54 444 481
55-59 456 491
60-64 535 585
65-69 282 341
70-74 105 159
75+ 44 58

Findings: In this chart, we have considered the records where the implicit salaries are mentioned. Both the barchart and the tables highlight that the number of males taking the survey is higher than the number of women, independent of their age range.

Bar Plot: Mean Salary by Age Range and Gender

age_gender_stats <- decoded_data %>%
  filter(!is.na(E14_1), !is.na(Age_16groups), !is.na(B3)) %>%
  group_by(Age_16groups, B3) %>%
  summarize(
    mean_salary = mean(E14_1),
    se = sd(E14_1) / sqrt(n()),
    lower_ci = mean_salary - 1.96 * se,
    upper_ci = mean_salary + 1.96 * se,
    n = n(),
    .groups = "drop"
  ) %>%
  filter(n >= 10) %>%
  mutate(salary_label = paste0(format(round(mean_salary), big.mark = ",")))
ggplot(age_gender_stats, 
       aes(x = Age_16groups, y = mean_salary, 
           color = B3, group = B3)) +
  geom_line(linewidth = 1.2) +
  geom_pointrange(
    aes(ymin = lower_ci, ymax = upper_ci),
    position = position_dodge(width = 0.2),
    size = 0.7
  ) +
  geom_text(aes(y = upper_ci, label = salary_label),
            position = position_dodge(width = 0.5),
            vjust = -0.5, size = 3, color = "black") +
  labs(
    title = "Mean Salary by Age Group and Gender with 95% Confidence Intervals",
    x = "Age Category", 
    y = "Mean Salary (AMD)",
    color = "Gender"
  ) +
  scale_y_continuous(labels = scales::comma) +
  theme_minimal()

Findings: In this chart, we have considered the records where the implicit salaries are mentioned. We can see that the salary of males in the sample is considerably higher and the condifence interval is bigger. However, the length of confidence intervals for the mean salary of males are longer, which means that we are not as much certain about the mean as for the females. The lower bounds of the confidence intervals of males’ mean salaries are closers to the females’ mean salaries.

Mean Salary with 95% Confidence Intervals

decoded_data <- decoded_data%>%
  mutate(
    B8 = case_when(
      B8 == 1 ~ "Up tp 2000",
      B8 == 2 ~ "2001-2005",
      B8 == 3 ~ "2006-2010",
      B8 == 4 ~ "Since 2012"
    )
  )

Based on the salary they have provided.

correct_order <- c("Up tp 2000", "2001-2005", "2006-2010", "Since 2012")

plot_data <- decoded_data %>%
  mutate(
    graduation_year_ordered = factor(
      B8,
      levels = correct_order,
      ordered = TRUE
    )
  ) %>%
  filter(!is.na(E14_1)) %>%
  group_by(graduation_year_ordered, B3) %>%  # Group by the ordered factor
  summarize(
    mean_salary = mean(E14_1),
    se = sd(E14_1) / sqrt(n()),
    lower_ci = mean_salary - 1.96 * se,
    upper_ci = mean_salary + 1.96 * se,
    .groups = "drop"  # Explicitly drop grouping
  ) %>%
  mutate(salary_label = paste0(format(round(mean_salary), big.mark = ","), " AMD"))

ggplot(plot_data, aes(x = graduation_year_ordered, y = mean_salary, 
                     color = B3, group = B3)) +
  geom_pointrange(aes(ymin = lower_ci, ymax = upper_ci),
                 position = position_dodge(width = 0.5)) +
  geom_line(position = position_dodge(width = 0.5)) +
  geom_text(aes(y = upper_ci, label = salary_label),
            position = position_dodge(width = 0.5),
            vjust = -0.5, size = 3, color = "black") +
  labs(title = "Mean Salary with 95% Confidence Intervals",
       x = "Graduation Year", y = "Mean Salary (AMD)",
       color = "Gender") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
Warning: Removed 1 row containing missing values or values outside the scale range (`geom_segment()`).
Warning: Removed 1 row containing missing values or values outside the scale range (`geom_text()`).

Let’s also see the count of men and women based on the graduation year.

graduation_summary <- decoded_data %>%
  filter(!is.na(B3), !is.na(B8)) %>%
  count(Gender = B3, Graduation_Year = B8, name = "Count") %>%

  group_by(Graduation_Year) %>%
  mutate(Percentage = Count / sum(Count) * 100) %>%
  ungroup() %>%
  
  mutate(Percentage_Label = paste0(round(Percentage, 1), "%")) %>%
  
  select(Gender, Graduation_Year, Count, Percentage, Percentage_Label) %>%
  arrange(Graduation_Year, Gender)

print(graduation_summary)

Findings: In this chart, we have considered the records where the implicit salaries are mentioned. We see that the number of females is bigger here. However, the mean salary of the males is still higher, with bigger confidence intervals as in the previous chart.

Can We Find the Mean Salary by Work Location and Gender

decoded_data <- decoded_data%>%
mutate(
    J3_1 = case_when(
      J3_1 == 1 ~ "Armenia",
      J3_1 == 2 ~ "Abroad",
      J3_1 == 3 ~ "No Paid Job"
      
    )
  ) %>%
mutate(
    J3_2 = case_when(
      J3_2 == 1 ~ "Armenia",
      J3_2 == 2 ~ "Abroad",
      J3_2 == 3 ~ "No Paid Job"
      
    )
  )

unique(cleaned_data['J3_1'])
unique(decoded_data['J3_2'])

It comes out that we cannot work with columns J3_1 and J3_2, which specify if the survey taker works in Armenia/abroad/both/no paid job. The reason is that when cleaning the data, we kept only the records where salary range or exact salary is mentioned.

decoded_data <- decoded_data%>%
  mutate(
    E10 = case_when(
      E10 == 1 ~ "Public",
      E10 == 2 ~ "NGO",
      E10 == 3 ~ "Private",
      E10 == 4 ~ "Self-emplyed"
    )
  ) %>%
  mutate(
    F6 = case_when(
      F6 == 1 ~ "Public",
      F6 == 2 ~ "NGO",
      F6 == 3 ~ "Private",
      F6 == 4 ~ "Self-employed"
    )
  )

Let’s see how many records we have with filled primary job and secondary ones.

primary_job_count <- decoded_data %>%
  filter(!is.na(E10)) %>%  
  count(B3, name = "count")  
primary_job_count
secondary_job_count <- decoded_data %>%
  filter(!is.na(F6)) %>%  
  count(B3, name = "count")

secondary_job_count
plot_data <- decoded_data %>%
  select(gender = B3, salary = E14_1, ownership = E10) %>%  
  filter(!is.na(salary), !is.na(ownership)) %>%              
  mutate(ownership = factor(ownership)) 

summary_stats <- plot_data %>%
  group_by(gender, ownership) %>%
  summarize(
    mean_salary = mean(salary),
    se = sd(salary) / sqrt(n()),
    lower_ci = mean_salary - 1.96 * se,
    upper_ci = mean_salary + 1.96 * se,
    n = n(),
    .groups = "drop"
  ) %>%
  filter(n >= 10) 
ggplot(summary_stats, 
       aes(x = ownership, y = mean_salary, fill = gender)) +
  geom_col(position = position_dodge(width = 0.8), width = 0.7) +
  geom_errorbar(
    aes(ymin = lower_ci, ymax = upper_ci),
    position = position_dodge(width = 0.8),
    width = 0.2,
    color = "black"
  ) +
  geom_text(
    aes(label = paste0(round(mean_salary/1000, 1), "k \n(n=", n, ")"),
        y = upper_ci),
    position = position_dodge(width = 0.8),
    vjust = -0.5,
    size = 3
  ) +
  labs(
    title = "Mean Salary (AMD) by Company Ownership (Primary Job)",
    subtitle = "Error bars show 95% confidence intervals",
    x = "Ownership Type",
    y = "Mean Salary (AMD)",
    fill = "Gender"
  ) +
  scale_y_continuous(labels = scales::comma) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Findings: In this chart, we have considered the records where the implicit salaries are mentioned. Concentrating on the chart above, we can see that only females are recorded as self-employed (keeping in mind that the data is filtered to keep only records with mentioned salary). The analysis also shows that males earn more in NGOs, Private and Public enterprises, but the highest difference is in Private companies. Although there are more females who answered these questions then males, the difference still exists.

mean_salary_by_region <- decoded_data %>%
  select(gender = B3, region = A3, salary = E14_1) %>%
  filter(!is.na(region), !is.na(gender), !is.na(salary)) %>%
  group_by(region, gender) %>%
  summarise(mean_salary = mean(salary, na.rm = TRUE),
            median_salary = median(salary, na.rm = TRUE), 
            min_salary = min(salary, na.rm = TRUE), 
            max_salary = max(salary, na.rm = TRUE))
`summarise()` has grouped output by 'region'. You can override using the `.groups` argument.
  
mean_salary_by_region
difference_in_mean_salary_by_region <- mean_salary_by_region %>%
  pivot_wider(names_from = gender, values_from = mean_salary) %>%
  mutate(wage_gap = Male - Female) %>%
  select(region, wage_gap)

difference_in_mean_salary_by_region
armenia_map <- st_read("armenia.json")
Reading layer `armenia' from data source `D:\Statistics\Final Project\armenia.json' using driver `GeoJSON'
Simple feature collection with 11 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 43.43629 ymin: 38.8637 xmax: 46.60261 ymax: 41.29045
Geodetic CRS:  WGS 84
region_name_map <- tibble::tibble(
  map_name = c("Tavush", "Lori", "Shirak", "Gegharkunik", "Vayots Dzor", 
               "Syunik", "Ararat", "Aragatsotn", "Armavir", "Kotayk", "Erevan"),
  region = c("Tavush", "Lori", "Shirak", "Gegharkunik", "Vayoc Dzor",
             "Syuniq", "Ararat", "Aragatsotn", "Armavir", "Kotayq", "Yerevan")  # match your data
)

armenia_map <- armenia_map %>%
  left_join(region_name_map, by = c("name" = "map_name"))
wage_gap_map <- armenia_map %>%
  left_join(difference_in_mean_salary_by_region, by = "region")

ggplot(wage_gap_map) +
  geom_sf(aes(fill = wage_gap), color = "white") +
  scale_fill_gradientn(
    colors = c("navy", "skyblue", "yellow", "orange", "red"),
    na.value = "gray90",
    name = "Wage Gap (AMD)"
  ) +
  labs(
    title = "Gender Wage Gap by Region (Armenia)",
    subtitle = "Difference in mean salary: Male - Female",
    caption = "Data: Your Survey"
  ) +
  theme_minimal()

p <- ggplot(wage_gap_map) +
  geom_sf(aes(fill = wage_gap, text = paste("Region:", name, "<br>Wage Gap:", wage_gap))) +
  scale_fill_viridis_c() +
  theme_minimal()
Warning in layer_sf(geom = GeomSf, data = data, mapping = mapping, stat = stat,  :
  Ignoring unknown aesthetics: text
ggplotly(p, tooltip = "text")

Findings: As shown in the map, there is a wage gap in all regions of Armenia, which fluctuates roughly between 50000 and 25000 AMD, with the smallest gap present in Ararat and the biggest in Armavir.

Urban vs Rural mean salaries

urban_rural_salary <- decoded_data %>%
  select(settlement = A5, gender = B3, salary = E14_1) %>%
  filter(!is.na(settlement), !is.na(gender), !is.na(salary)) %>%
  group_by(settlement, gender) %>%
  summarise(mean_salary = mean(salary), min_salary = min(salary), max_salary = max(salary))
`summarise()` has grouped output by 'settlement'. You can override using the `.groups` argument.
urban_rural_salary

ggplot(decoded_data, aes(x = A5, y = E14_1, fill = A5)) +
  geom_boxplot(outlier.color = "red", outlier.alpha = 0.3) +
    coord_cartesian(ylim = c(0, 500000)) +
  labs(
    title = "Income Distribution: Urban vs Rural",
    x = "Settlement Type",
    y = "Salary (AMD)"
  ) +
  theme_minimal() +
  scale_fill_manual(values = c("Urban" = "#66c2a5", "Rural" = "#fc8d62"))
Warning: Removed 3575 rows containing non-finite outside the scale range (`stat_boxplot()`).

Findings: The mean salary in urban settlements is higher than in rural settlements. Moreover, the range of salaries is much bigger than that of urban salaries.

LS0tDQp0aXRsZTogIlN0YXRpc3RpY3MgUHJvamVjdCBWaXN1YWxpemF0aW9ucyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShwbG90bHkpDQpgYGANCg0KYGBge3J9DQpkYXRhIDwtIHJlYWRfZXhjZWwoImRhdGEueGxzeCIsIHNoZWV0ID0gIkxGU19ZZWFyXzIwMjMiKQ0KYGBgDQoNCmBgYHtyfQ0KcmVnaW9ucyA8LSBjKA0KICAiWWVyZXZhbiIsDQogICJBcmFnYXRzb3RuIiwNCiAgIkFyYXJhdCIsDQogICJBcm1hdmlyIiwNCiAgIkdlZ2hhcmt1bmlrIiwNCiAgIkxvcmkiLA0KICAiS290YXlxIiwNCiAgIlNoaXJhayIsDQogICJTeXVuaXEiLA0KICAiVmF5b2MgRHpvciIsDQogICJUYXZ1c2giDQopDQpgYGANCg0KYGBge3J9DQpwZW9wbGVfYnlfcmVnaW9ucyA8LSBkYXRhICU+JQ0KICBncm91cF9ieShBMykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBuID0gbigpDQogICkgJT4lDQogIG11dGF0ZShBMyA9IGZhY3RvcihBMywgbGV2ZWxzID0gMToxMSwgbGFiZWxzID0gcmVnaW9ucykpICU+JQ0KICByZW5hbWUoDQogICAgcmVnaW9uID0gQTMsDQogICAgcG9wdWxhdGlvbiA9IG4NCiAgKQ0KDQpwZW9wbGVfYnlfcmVnaW9ucw0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHBlb3BsZV9ieV9yZWdpb25zLCBhZXMoeCA9IHJlZ2lvbiwgeSA9IHBvcHVsYXRpb24pKSArDQogIGdlb21fY29sKGZpbGwgPSAicGx1bTMiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUG9wdWxhdGlvbiBieSBSZWdpb25zIiwNCiAgICB4ID0gIlJlZ2lvbnMiLA0KICAgIHkgPSAiUG9wdWxhdGlvbiINCiAgKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KYGBge3J9DQp1cmJhbl9ydXJhbCA8LSBkYXRhICU+JQ0KICBncm91cF9ieShBNSkgJT4lDQogIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgbXV0YXRlKEE1ID0gZmFjdG9yKEE1LCBsZXZlbHMgPSBjKDEsIDIpLCBsYWJlbHMgPSBjKCJVcmJhbiIsICJSdXJhbCIpKSkNCg0KdXJiYW5fcnVyYWwNCmBgYA0KDQpgYGB7cn0NCmdlbmRlcl9yYXRpbyA8LSBkYXRhICU+JQ0KICBncm91cF9ieShCMykgJT4lDQogIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgbXV0YXRlKEIzID0gZmFjdG9yKEIzLCBsZXZlbHMgPSBjKDEsIDIpLCBsYWJlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIpKSkNCg0KZ2VuZGVyX3JhdGlvDQpgYGANCg0KYGBge3J9DQphZ2VfZ3JvdXBzIDwtIGMoDQogICIwIC0gNCIsDQogICI1IC0gOSIsDQogICIxMCAtIDE0IiwNCiAgIjE1IC0gMTkiLA0KICAiMjAgLSAyNCIsDQogICIyNSAtIDI5IiwNCiAgIjMwIC0gMzQiLA0KICAiMzUgLSAzOSIsDQogICI0MCAtIDQ0IiwNCiAgIjQ1IC0gNDkiLA0KICAiNTAgLSA1NCIsDQogICI1NSAtIDU5IiwNCiAgIjYwIC0gNjQiLA0KICAiNjUgLSA2OSIsDQogICI3MCAtIDc0IiwNCiAgIjc1KyINCikNCmBgYA0KDQpgYGB7cn0NCnBlb3BsZV9ieV9hZ2UgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkoQWdlXzE2Z3JvdXBzKSAlPiUNCiAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBtdXRhdGUoQWdlXzE2Z3JvdXBzID0gZmFjdG9yKEFnZV8xNmdyb3VwcywgbGV2ZWxzID0gMToxNiwgbGFiZWxzID0gYWdlX2dyb3VwcykpICU+JQ0KICByZW5hbWUoDQogICAgYWdlX2dyb3VwID0gQWdlXzE2Z3JvdXBzLA0KICAgIHBvcHVsYXRpb24gPSBuDQogICkNCg0KcGVvcGxlX2J5X2FnZQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHBlb3BsZV9ieV9hZ2UsIGFlcyh4ID0gYWdlX2dyb3VwcywgeSA9IHBvcHVsYXRpb24pKSArDQogIGdlb21fY29sKGZpbGwgPSAicGx1bTMiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUG9wdWxhdGlvbiBieSBBZ2UgR3JvdXAiLA0KICAgIHggPSAiQWdlIEdyb3VwIiwNCiAgICB5ID0gIlBvcHVsYXRpb24iDQogICkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNCmBgYHtyfQ0KZWR1Y2F0aW9uYWxfbGV2ZWxzIDwtIGMoIklsbGl0ZXJhdGUiLCAiTm8gcHJpbWFyeSIsICJQcmltYXJ5IiwgIkJhc2ljIiwgIlNlY29uZGFyeSAvIGhpZ2giLCANCiAgICAgICAgICAgICAgICAgICAgICAiVm9jYXRpb25hbCIsICJTZWNvbmRhcnkgc3BlY2lhbGl6ZWQiLCAiQmFjaGVsb3IncyBkZWdyZWUiLCANCiAgICAgICAgICAgICAgICAgICAgICAiTWFzdGVyJ3MgZGVncmVlIiwgIkNlcnRpZmllZCBzcGVjaWFsaXN0IiwgDQogICAgICAgICAgICAgICAgICAgICAgIlBvc3QtZ3JhZHVhdGUgKFBoLkQsIGRvY3RvcmF0ZSkiKQ0KDQpgYGANCg0KYGBge3J9DQpwZW9wbGVfYnlfZWR1Y2F0aW9uIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KEI3KSAlPiUNCiAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBtdXRhdGUoQjcgPSBmYWN0b3IoQjcsIGxldmVscyA9IDE6MTEsIGxhYmVscyA9IGVkdWNhdGlvbmFsX2xldmVscykpICU+JQ0KICByZW5hbWUoDQogICAgZWR1Y2F0aW9uYWxfbGV2ZWwgPSBCNywNCiAgICBwb3B1bGF0aW9uID0gbg0KICApDQoNCnBlb3BsZV9ieV9lZHVjYXRpb24NCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwZW9wbGVfYnlfZWR1Y2F0aW9uLCBhZXMoeCA9IGVkdWNhdGlvbmFsX2xldmVsLCB5ID0gcG9wdWxhdGlvbikpICsNCiAgZ2VvbV9jb2woZmlsbCA9ICJwbHVtMyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQb3B1bGF0aW9uIGJ5IEVkdWNhdGlvbmFsIExldmVsIiwNCiAgICB4ID0gIkVkdWNhdGlvbmFsIExldmVsIiwNCiAgICB5ID0gIlBvcHVsYXRpb24iDQogICkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNCmBgYHtyfQ0KbmFjZV9zZWN0b3JzIDwtIGMoDQogICJBZ3JpY3VsdHVyZSwgRm9yZXN0cnkgYW5kIEZpc2hpbmciLA0KICAiTWluaW5nIGFuZCBRdWFycnlpbmciLA0KICAiTWFudWZhY3R1cmluZyIsDQogICJFbGVjdHJpY2l0eSwgR2FzLCBTdGVhbSBhbmQgQWlyIENvbmRpdGlvbmluZyBTdXBwbHkiLA0KICAiV2F0ZXIgU3VwcGx5OyBTZXdlcmFnZSwgV2FzdGUgTWFuYWdlbWVudCBhbmQgUmVtZWRpYXRpb24gQWN0aXZpdGllcyIsDQogICJDb25zdHJ1Y3Rpb24iLA0KICAiV2hvbGVzYWxlIGFuZCBSZXRhaWwgVHJhZGU7IFJlcGFpciBvZiBNb3RvciBWZWhpY2xlcyBhbmQgTW90b3JjeWNsZXMiLA0KICAiVHJhbnNwb3J0YXRpb24gYW5kIFN0b3JhZ2UiLA0KICAiQWNjb21tb2RhdGlvbiBhbmQgRm9vZCBTZXJ2aWNlIEFjdGl2aXRpZXMiLA0KICAiUHVibGlzaGluZywgQnJvYWRjYXN0aW5nLCBhbmQgQ29udGVudCBQcm9kdWN0aW9uIGFuZCBEaXN0cmlidXRpb24gQWN0aXZpdGllcyIsDQogICJUZWxlY29tbXVuaWNhdGlvbiwgQ29tcHV0ZXIgUHJvZ3JhbW1pbmcsIENvbnN1bHRpbmcsIENvbXB1dGluZyBJbmZyYXN0cnVjdHVyZSwgYW5kIG90aGVyIEluZm9ybWF0aW9uIFNlcnZpY2UgQWN0aXZpdGllcyIsDQogICJGaW5hbmNpYWwgYW5kIEluc3VyYW5jZSBBY3Rpdml0aWVzIiwNCiAgIlJlYWwgRXN0YXRlIEFjdGl2aXRpZXMiLA0KICAiUHJvZmVzc2lvbmFsLCBTY2llbnRpZmljIGFuZCBUZWNobmljYWwgQWN0aXZpdGllcyIsDQogICJBZG1pbmlzdHJhdGl2ZSBhbmQgU3VwcG9ydCBTZXJ2aWNlIEFjdGl2aXRpZXMiLA0KICAiUHVibGljIEFkbWluaXN0cmF0aW9uIGFuZCBEZWZlbmNlOyBDb21wdWxzb3J5IFNvY2lhbCBTZWN1cml0eSIsDQogICJFZHVjYXRpb24iLA0KICAiSHVtYW4gSGVhbHRoIGFuZCBTb2NpYWwgV29yayBBY3Rpdml0aWVzIiwNCiAgIkFydHMsIFNwb3J0cyBhbmQgUmVjcmVhdGlvbiIsDQogICJPdGhlciBTZXJ2aWNlIEFjdGl2aXRpZXMiLA0KICAiQWN0aXZpdGllcyBvZiBIb3VzZWhvbGRzIGFzIEVtcGxveWVyczsgVW5kaWZmZXJlbnRpYXRlZCBHb29kcyBhbmQgU2VydmljZXMgUHJvZHVjaW5nIEFjdGl2aXRpZXMgb2YgSG91c2Vob2xkcyBmb3IgT3duIFVzZSINCikNCmBgYA0KDQpgYGB7cn0NCmVtcGxveWVlc19ieV9pbmR1c3RyeSA8LSBkYXRhICU+JQ0KICBncm91cF9ieShFNF8yMWdyb3Vwc19OQUNFX3Jldl8yLjIpICU+JQ0KICBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIG11dGF0ZShFNF8yMWdyb3Vwc19OQUNFX3Jldl8yLjIgPSBmYWN0b3IoRTRfMjFncm91cHNfTkFDRV9yZXZfMi4yLCBsZXZlbHMgPSAxOjIxLCBsYWJlbHMgPSBuYWNlX3NlY3RvcnMpKSAlPiUNCiAgcmVuYW1lKA0KICAgIGluZHVzdHJ5ID0gRTRfMjFncm91cHNfTkFDRV9yZXZfMi4yLA0KICAgIGVtcGxveWVlX251bWJlciA9IG4NCiAgKQ0KDQplbXBsb3llZXNfYnlfaW5kdXN0cnkNCmBgYA0KDQpgYGB7cn0NCmV4YWN0X3NhbGFyeV9kYXRhX3BvaW50cyA8LSBkYXRhICU+JQ0KICBzZWxlY3QoRTE0XzEpICU+JQ0KICBuYS5vbWl0KCkgJT4lDQogIHN1bW1hcmlzZShuID0gbigpKQ0KDQpleGFjdF9zYWxhcnlfZGF0YV9wb2ludHMNCmBgYA0KYGBge3J9DQpleGFjdF9zYWxhcnlfZGVzYyA8LSBkYXRhICU+JQ0KICBzZWxlY3QoRTE0XzEpICU+JQ0KICBuYS5vbWl0KCkgJT4lDQogIHN1bW1hcmlzZShtZWFuID0gbWVhbihFMTRfMSksIG1heCA9IG1heChFMTRfMSksIG1pbiA9IG1pbihFMTRfMSksIG1lZGlhbiA9IG1lZGlhbihFMTRfMSkpDQoNCmV4YWN0X3NhbGFyeV9kZXNjDQpgYGANCmBgYHtyfQ0KbWVhbl9zYWxhcnlfYnlfZ2VuZGVyIDwtIGRhdGEgJT4lDQogIHNlbGVjdChFMTRfMSwgQjMpICU+JQ0KICBtdXRhdGUoQjMgPSBmYWN0b3IoQjMsIGxldmVscyA9IDE6MiwgbGFiZWxzID0gYygiTWFsZSIsICJGZW1hbGUiKSkpICU+JQ0KICBuYS5vbWl0KCkgJT4lDQogIGdyb3VwX2J5KEIzKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKEUxNF8xKSwgbWVkaWFuID0gbWVkaWFuKEUxNF8xKSwgbWluID0gbWluKEUxNF8xKSwgbWF4ID0gbWF4KEUxNF8xKSkNCg0KbWVhbl9zYWxhcnlfYnlfZ2VuZGVyDQpgYGANCmBgYHtyfQ0Kc2FsYXJ5X2RhdGEgPC0gZGF0YSAlPiUNCiAgc2VsZWN0KHNhbGFyeSA9IEUxNF8xLCBnZW5kZXJfY29kZSA9IEIzKSAlPiUNCiAgbXV0YXRlKA0KICAgIGdlbmRlciA9IGZhY3RvcihnZW5kZXJfY29kZSwgbGV2ZWxzID0gYygxLCAyKSwgbGFiZWxzID0gYygiTWFsZSIsICJGZW1hbGUiKSkNCiAgKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShzYWxhcnkpLCAhaXMubmEoZ2VuZGVyKSkNCg0KZ2dwbG90KHNhbGFyeV9kYXRhLCBhZXMoeCA9IGdlbmRlciwgeSA9IHNhbGFyeSwgZmlsbCA9IGdlbmRlcikpICsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgNTAwMDAwKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNYWxlIiA9ICIjNTZCNEU5IiwgIkZlbWFsZSIgPSAiI0U3OEFDMyIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU2FsYXJ5IERpc3RyaWJ1dGlvbiBieSBHZW5kZXIiLA0KICAgIHggPSAiR2VuZGVyIiwNCiAgICB5ID0gIlNhbGFyeSINCiAgKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQpgYGB7cn0NCmluY29tZV9yYW5nZXMgPC0gYygNCiAgIlVwIHRvIDU1IDAwMCBBTUQiLA0KICAiNTUgMDAwIEFNRCIsDQogICI1NSAwMDEgLSAxMTAgMDAwIEFNRCIsDQogICIxMTAgMDAxIC0gMjIwIDAwMCBBTUQiLA0KICAiMjIwIDAwMSAtIDQ0MCAwMDAgQU1EIiwNCiAgIjQ0MCAwMDEgLSA2MDAgMDAwIEFNRCIsDQogICI2MDAgMDAxIC0gNzAwIDAwMCBBTUQiLA0KICAiUmVmdXNlZCB0byBhbnN3ZXIiLA0KICAiRG8gbm90IGtub3cgLyBkaWZmaWN1bHQgdG8gYW5zd2VyIg0KKQ0KYGBgDQoNCmBgYHtyfQ0KY2F0ZWdvcmljYWxfc2FsYXJ5X2RhdGFfcG9pbnRzIDwtIGRhdGEgJT4lDQogIHNlbGVjdChFMTUpICU+JQ0KICBuYS5vbWl0KCkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfZGF0YV9wb2ludHMgPSBuKCkpDQoNCmNhdGVnb3JpY2FsX3NhbGFyeV9kYXRhX3BvaW50cw0KYGBgDQoNCmBgYHtyfQ0KY2F0ZWdvcmljYWxfc2FsYXJ5X2ZyZXF1ZW5jeSA8LSBkYXRhICU+JQ0KICBncm91cF9ieShFMTUpICU+JQ0KICBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIG5hLm9taXQoKSAlPiUNCiAgbXV0YXRlKEUxNSA9IGZhY3RvcihFMTUsIGxldmVscyA9IDE6OSwgbGFiZWxzID0gaW5jb21lX3JhbmdlcykpICU+JQ0KICByZW5hbWUoDQogICAgaW5jb21lX3JhbmdlID0gRTE1LA0KICAgIGZyZXF1ZW5jeSA9IG4NCiAgKQ0KDQpjYXRlZ29yaWNhbF9zYWxhcnlfZnJlcXVlbmN5DQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoY2F0ZWdvcmljYWxfc2FsYXJ5X2ZyZXF1ZW5jeSwgYWVzKHggPSBpbmNvbWVfcmFuZ2UsIHkgPSBmcmVxdWVuY3kpKSArDQogIGdlb21fY29sKGZpbGwgPSAicGx1bTMiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU2FsYXJ5IEhpc3RvZ3JhbSIsDQogICAgeCA9ICJJbmNvbWUgUmFuZ2VzIiwNCiAgICB5ID0gIkZyZXF1ZW5jeSINCiAgKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQoNCmBgYA0KDQpEYXRhIENsZWFuaW5nDQoNCmNoZWNraW5nIHRvIHNlZSBob3cgbWFueSByb3dzIGhhdmUgbW9yZSB0aGFuIDUwJSBtaXNzaW5nIGRhdGEgDQooZnJvbSB0aGUgY29sdW1ucyB3ZSBhcmUgZ29pbmcgdG8gd29yayBvbikNCmBgYHtyfQ0KDQpjb2xzX3RvX3dvcmsgPC0gZGF0YVssIGMoJ0EzJywgJ0E1JywgJ0E2X01vbnRoJywgJ0E2X1llYXInLCAnQjMnLCAnQWdlXzE2Z3JvdXBzJywgJ0I3JywgJ0I4JywgDQogICAgICAgICAgICAgICAgICAgICAgICAnQjhfWWVhcicsICdCOScsICdCMTAnLCAnQjExJywgJ0MxJywgJ0M5JywgJ0M0JywgJ0MzJywgJ0QxJywgJ0QyJywgJ0QzJywgJ0UyXzlncm91cCcsIA0KICAgICAgICAgICAgICAgICAgICAgICAgJ0U0XzIxZ3JvdXBzX05BQ0VfcmV2XzIuMicsICdFNScsICdFNicsICdFNycsICdFOScsICdFMTAnLCAnRTEzJywgJ0UxNF8xJywgJ0UxNF8yJywgJ0UxNScsICdFMTYnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICdFMTcnLCAnRTE5JywgJ0UyMycsICdFMjQnLCAnRjEnLCAnRjJfOWdyb3VwJywgJ0YzXzIxZ3JvdXBzX05BQ0VfcmV2XzIuMicsICdGNCcsICdGNScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgJ0Y2JywgJ0Y4XzEnLCAnRjhfMicsICdHMl8xJywgJ0cyXzInLCAnRzJfM1RvdGFsJywgJ0czJywgJ0oxXzRncm91cCcsICdKM18xJywgJ0ozXzInLCAnSjNfTGFzdEpvYicpXQ0KbWlzc2luZ19wZXJfcm93IDwtIHJvd1N1bXMoaXMubmEoY29sc190b193b3JrKSkgDQp0b3RhbF9jb2xzIDwtIGxlbmd0aChjb2xzX3RvX3dvcmspDQpleGNlZWRzIDwtIHdoaWNoKG1pc3NpbmdfcGVyX3JvdyA+IDAuNSAqIHRvdGFsX2NvbHMpDQpnb29kX3Jvd3MgPC1sZW5ndGgoZXhjZWVkcykNCnByaW50KGdvb2Rfcm93cykNCmBgYA0KDQoNCmNoZWNrIGhvdyBtYW55IGVtcHR5IHJvd3MgdGhlcmUgYXJlDQpgYGB7cn0NCnN1bShhcHBseShkYXRhLCAxLCBmdW5jdGlvbihyb3cpIGFsbChpcy5uYShyb3cpKSkpDQpgYGANCmNoZWNrIGhvdyBtYW55IHJvd3MgYXJlIG1pc3NpbmcgdmFsdWVzIG9mIGltcG9ydGFudCBjb2x1bW5zDQpgYGB7cn0NCmNvbHNfdG9fY2hlY2sgPC0gYygnQTMnLCAnQTUnLCAnQTZfTW9udGgnLCAnQTZfWWVhcicsICdCMycsICdBZ2VfMTZncm91cHMnLCAnQjcnLCAnQjgnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICdCOF9ZZWFyJywgJ0I5JywgJ0IxMCcsICdCMTEnLCAnQzEnLCAnQzknLCAnQzQnLCAnQzMnLCAnRDEnLCAnRDInLCAnRDMnLCAnRTJfOWdyb3VwJywgDQogICAgICAgICAgICAgICAgICAgICAgICAnRTRfMjFncm91cHNfTkFDRV9yZXZfMi4yJywgJ0U1JywgJ0U2JywgJ0U3JywgJ0U5JywgJ0UxMCcsICdFMTMnLCAnRTE0XzEnLCAnRTE0XzInLCAnRTE1JywgJ0UxNicsIA0KICAgICAgICAgICAgICAgICAgICAgICAgJ0UxNycsICdFMTknLCAnRTIzJywgJ0UyNCcsICdGMScsICdGMl85Z3JvdXAnLCAnRjNfMjFncm91cHNfTkFDRV9yZXZfMi4yJywgJ0Y0JywgJ0Y1JywgDQogICAgICAgICAgICAgICAgICAgICAgICAnRjYnLCAnRjhfMScsICdGOF8yJywgJ0cyXzEnLCAnRzJfMicsICdHMl8zVG90YWwnLCAnRzMnLCAnSjFfNGdyb3VwJywgJ0ozXzEnLCAnSjNfMicsICdKM19MYXN0Sm9iJykgDQpzdW0ocm93U3Vtcyhpcy5uYShkYXRhW2NvbHNfdG9fY2hlY2tdKSkgPiAwKQ0KYGBgDQoNCg0KYGBge3J9DQpzdW0oIWlzLm5hKGRhdGEkRTE0XzIpKQ0KYGBgDQpgYGB7cn0NCmdldF9tb2RlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgdW5pcXggPC0gdW5pcXVlKHgpDQogIHVuaXF4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1bmlxeCkpKV0NCn0NCmBgYA0KDQpgYGB7cn0NCmRhdGEgJT4lDQogIGZpbHRlcighaXMubmEoRTE0XzIpKSAlPiUNCiAgc2VsZWN0KEUxNF8yKSAlPiUNCiAgc3VtbWFyaXNlKG1vZGUgPSBnZXRfbW9kZShFMTRfMikpDQpgYGANCmBgYHtyfQ0KZGF0YSAlPiUNCiAgZmlsdGVyKCFpcy5uYShFMTRfMikpICU+JQ0KICBjb3VudChFMTRfMiwgc29ydCA9IFRSVUUpDQpgYGANCg0KKioqRGVzY3JpcHRpdmUgRGF0YSBBbmFseXNpcyBhbmQgVmlzdWFsaXphdGlvbnMqKioNCg0KYGBge3J9DQpjbGVhbmVkX2RhdGEgPC0gcmVhZF9leGNlbCgiY2xlYW5lZF9kYXRhLnhsc3giKQ0KYGBgDQoNCipCYXJwbG90OiBDb3VudHMgYnkgQWdlIFJhbmdlIGFuZCBHZW5kZXIqDQoNCkRlY29kaW5nIGRhdGENCmBgYHtyfQ0KZGVjb2RlZF9kYXRhIDwtIGNsZWFuZWRfZGF0YSAlPiUNCiAgbXV0YXRlKA0KICAgIEIzID0gY2FzZV93aGVuKA0KICAgICAgQjMgPT0gMSB+ICJNYWxlIiwNCiAgICAgIEIzID09IDIgfiAiRmVtYWxlIiwNCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgKQ0KICApICU+JQ0KICBtdXRhdGUoDQogICAgQWdlXzE2Z3JvdXBzID0gY2FzZV93aGVuKA0KICAgICAgQWdlXzE2Z3JvdXBzID09IDEgfiAiMC00IiwNCiAgICAgIEFnZV8xNmdyb3VwcyA9PSAyIH4gIjUtOSIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gMyB+ICIxMC0xNCIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gNCB+ICIxNS0xOSIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gNSB+ICIyMC0yNCIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gNiB+ICIyNS0yOSIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gNyB+ICIzMC0zNCIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gOCB+ICIzNS0zOSIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gOSB+ICI0MC00NCIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gMTAgfiAiNDUtNDkiLA0KICAgICAgQWdlXzE2Z3JvdXBzID09IDExIH4gIjUwLTU0IiwNCiAgICAgIEFnZV8xNmdyb3VwcyA9PSAxMiB+ICI1NS01OSIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gMTMgfiAiNjAtNjQiLA0KICAgICAgQWdlXzE2Z3JvdXBzID09IDE0IH4gIjY1LTY5IiwNCiAgICAgIEFnZV8xNmdyb3VwcyA9PSAxNSB+ICI3MC03NCIsDQogICAgICBBZ2VfMTZncm91cHMgPT0gMTYgfiAiNzUrIiwNCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgKQ0KICApICU+JQ0KICBtdXRhdGUoDQogICAgRTE1ID0gY2FzZV93aGVuKA0KICAgICAgRTE1ID09IDEgfiAiVXAgdG8gNTUgMDAwIEFNRCIsDQogICAgICBFMTUgPT0gMiB+ICI1NSAwMDAgQU1EIiwNCiAgICAgIEUxNSA9PSAzIH4gIjU1IDAwMSAtICAxMTAgMDAwIEFNRCIsDQogICAgICBFMTUgPT0gNCB+ICIxMTAgMDAxIC0gMjIwIDAwMCBBTUQiLA0KICAgICAgRTE1ID09IDUgfiAiMjIwIDAwMSAtIDQ0MCAwMDAgQU1EIiwNCiAgICAgIEUxNSA9PSA2IH4gIjQ0MCAwMDEgLSA2MDAgMDAwIEFNRCIsDQogICAgICBFMTUgPT0gNyB+ICI2MDAgMDAxIC0gNzAwIDAwMCBBTUQiLA0KICAgICAgRTE1ID09IDggfiAiUmVmdXNlZCB0byBhbnN3ZXIiLA0KICAgICAgRTE1ID09IDkgfiAiRG8gbm90IGtub3cgLyBkaWZmaWN1bHQgdG8gYW5zd2VyIiwNCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgKQ0KICApICU+JQ0KICBtdXRhdGUoDQogICAgQTMgPSBjYXNlX3doZW4oDQogICAgICBBMyA9PSAxIH4gIlllcmV2YW4iLA0KICAgICAgQTMgPT0gMiB+ICJBcmFnYXRzb3RuIiwNCiAgICAgIEEzID09IDMgfiAiQXJhcmF0IiwNCiAgICAgIEEzID09IDQgfiAiQXJtYXZpciIsDQogICAgICBBMyA9PSA1IH4gIkdlZ2hhcmt1bmlrIiwNCiAgICAgIEEzID09IDYgfiAiTG9yaSIsDQogICAgICBBMyA9PSA3IH4gIktvdGF5cSIsDQogICAgICBBMyA9PSA4IH4gIlNoaXJhayIsDQogICAgICBBMyA9PSA5IH4gIlN5dW5pcSIsDQogICAgICBBMyA9PSAxMCB+ICJWYXlvYyBEem9yIiwNCiAgICAgIEEzID09IDExIH4gIlRhdnVzaCIsDQogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICAgICkNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIEE1ID0gY2FzZV93aGVuKA0KICAgICAgQTUgPT0gMSB+ICJVcmJhbiIsDQogICAgICBBNSA9PSAyIH4gIlJ1cmFsIiwNCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgKQ0KICApDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGVjb2RlZF9kYXRhLCBhZXMoeCA9IGZhY3RvcihBZ2VfMTZncm91cHMpLCBmaWxsID0gZmFjdG9yKEIzKSkpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siKSArIA0KICBsYWJzKA0KICAgIHRpdGxlID0gIkFnZSBEaXN0cmlidXRpb24gYnkgR2VuZGVyIiwNCiAgICB4ID0gIkFnZSBSYW5nZSIsDQogICAgeSA9ICJDb3VudCIsDQogICAgZmlsbCA9ICJHZW5kZXIiDQogICkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNYWxlIiA9ICIjNTZCNEU5IiwgIkZlbWFsZSIgPSAiI0U3OEFDMyIpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpIA0KYGBgDQoNCkFsc28sIGxldCdzIGNhbGN1bGF0ZSB0aGlzIG51bWVyaWNhbGx5Lg0KYGBge3J9DQpnZW5kZXJfY291bnRzIDwtIGRlY29kZWRfZGF0YSAlPiUNCiAgZ3JvdXBfYnkoQWdlXzE2Z3JvdXBzLCBCMykgJT4lDQogIHN1bW1hcmlzZShDb3VudCA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikNCg0KZ2VuZGVyX2NvdW50c193aWRlIDwtIGdlbmRlcl9jb3VudHMgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBCMywgdmFsdWVzX2Zyb20gPSBDb3VudCwgdmFsdWVzX2ZpbGwgPSAwKSAlPiUNCiAgcmVuYW1lKCJBZ2UgUmFuZ2UiID0gQWdlXzE2Z3JvdXBzKQ0KDQojIGRpc3BsYXkNCmtuaXRyOjprYWJsZShnZW5kZXJfY291bnRzX3dpZGUsIGNhcHRpb24gPSAiR2VuZGVyIENvdW50IGJ5IEFnZSBHcm91cCIpDQpgYGANCkZpbmRpbmdzOiBJbiB0aGlzIGNoYXJ0LCB3ZSBoYXZlIGNvbnNpZGVyZWQgdGhlIHJlY29yZHMgd2hlcmUgdGhlIGltcGxpY2l0IHNhbGFyaWVzIGFyZSBtZW50aW9uZWQuDQpCb3RoIHRoZSBiYXJjaGFydCBhbmQgdGhlIHRhYmxlcyBoaWdobGlnaHQgdGhhdCB0aGUgbnVtYmVyIG9mIG1hbGVzIHRha2luZyB0aGUgc3VydmV5IGlzIGhpZ2hlciB0aGFuIHRoZSBudW1iZXIgb2Ygd29tZW4sIGluZGVwZW5kZW50IG9mIHRoZWlyIGFnZSByYW5nZS4NCg0KKkJhciBQbG90OiBNZWFuIFNhbGFyeSBieSBBZ2UgUmFuZ2UgYW5kIEdlbmRlcioNCmBgYHtyfQ0KYWdlX2dlbmRlcl9zdGF0cyA8LSBkZWNvZGVkX2RhdGEgJT4lDQogIGZpbHRlcighaXMubmEoRTE0XzEpLCAhaXMubmEoQWdlXzE2Z3JvdXBzKSwgIWlzLm5hKEIzKSkgJT4lDQogIGdyb3VwX2J5KEFnZV8xNmdyb3VwcywgQjMpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWVhbl9zYWxhcnkgPSBtZWFuKEUxNF8xKSwNCiAgICBzZSA9IHNkKEUxNF8xKSAvIHNxcnQobigpKSwNCiAgICBsb3dlcl9jaSA9IG1lYW5fc2FsYXJ5IC0gMS45NiAqIHNlLA0KICAgIHVwcGVyX2NpID0gbWVhbl9zYWxhcnkgKyAxLjk2ICogc2UsDQogICAgbiA9IG4oKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgJT4lDQogIGZpbHRlcihuID49IDEwKSAlPiUNCiAgbXV0YXRlKHNhbGFyeV9sYWJlbCA9IHBhc3RlMChmb3JtYXQocm91bmQobWVhbl9zYWxhcnkpLCBiaWcubWFyayA9ICIsIikpKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGFnZV9nZW5kZXJfc3RhdHMsIA0KICAgICAgIGFlcyh4ID0gQWdlXzE2Z3JvdXBzLCB5ID0gbWVhbl9zYWxhcnksIA0KICAgICAgICAgICBjb2xvciA9IEIzLCBncm91cCA9IEIzKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMS4yKSArDQogIGdlb21fcG9pbnRyYW5nZSgNCiAgICBhZXMoeW1pbiA9IGxvd2VyX2NpLCB5bWF4ID0gdXBwZXJfY2kpLA0KICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjIpLA0KICAgIHNpemUgPSAwLjcNCiAgKSArDQogIGdlb21fdGV4dChhZXMoeSA9IHVwcGVyX2NpLCBsYWJlbCA9IHNhbGFyeV9sYWJlbCksDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSwNCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDMsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk1lYW4gU2FsYXJ5IGJ5IEFnZSBHcm91cCBhbmQgR2VuZGVyIHdpdGggOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWxzIiwNCiAgICB4ID0gIkFnZSBDYXRlZ29yeSIsIA0KICAgIHkgPSAiTWVhbiBTYWxhcnkgKEFNRCkiLA0KICAgIGNvbG9yID0gIkdlbmRlciINCiAgKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpGaW5kaW5nczogSW4gdGhpcyBjaGFydCwgd2UgaGF2ZSBjb25zaWRlcmVkIHRoZSByZWNvcmRzIHdoZXJlIHRoZSBpbXBsaWNpdCBzYWxhcmllcyBhcmUgbWVudGlvbmVkLg0KV2UgY2FuIHNlZSB0aGF0IHRoZSBzYWxhcnkgb2YgbWFsZXMgaW4gdGhlIHNhbXBsZSBpcyBjb25zaWRlcmFibHkgaGlnaGVyIGFuZCB0aGUgY29uZGlmZW5jZSBpbnRlcnZhbCBpcyBiaWdnZXIuIEhvd2V2ZXIsIHRoZSBsZW5ndGggb2YgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHRoZSBtZWFuIHNhbGFyeSBvZiBtYWxlcyBhcmUgbG9uZ2VyLCB3aGljaCBtZWFucyB0aGF0IHdlIGFyZSBub3QgYXMgbXVjaCBjZXJ0YWluIGFib3V0IHRoZSBtZWFuIGFzIGZvciB0aGUgZmVtYWxlcy4gVGhlIGxvd2VyIGJvdW5kcyBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgbWFsZXMnIG1lYW4gc2FsYXJpZXMgYXJlIGNsb3NlcnMgdG8gdGhlIGZlbWFsZXMnIG1lYW4gc2FsYXJpZXMuDQoNCipNZWFuIFNhbGFyeSB3aXRoIDk1JSBDb25maWRlbmNlIEludGVydmFscyoNCmBgYHtyfQ0KZGVjb2RlZF9kYXRhIDwtIGRlY29kZWRfZGF0YSU+JQ0KICBtdXRhdGUoDQogICAgQjggPSBjYXNlX3doZW4oDQogICAgICBCOCA9PSAxIH4gIlVwIHRwIDIwMDAiLA0KICAgICAgQjggPT0gMiB+ICIyMDAxLTIwMDUiLA0KICAgICAgQjggPT0gMyB+ICIyMDA2LTIwMTAiLA0KICAgICAgQjggPT0gNCB+ICJTaW5jZSAyMDEyIg0KICAgICkNCiAgKQ0KYGBgDQoNCkJhc2VkIG9uIHRoZSBzYWxhcnkgdGhleSBoYXZlIHByb3ZpZGVkLg0KDQpgYGB7cn0NCmNvcnJlY3Rfb3JkZXIgPC0gYygiVXAgdHAgMjAwMCIsICIyMDAxLTIwMDUiLCAiMjAwNi0yMDEwIiwgIlNpbmNlIDIwMTIiKQ0KDQpwbG90X2RhdGEgPC0gZGVjb2RlZF9kYXRhICU+JQ0KICBtdXRhdGUoDQogICAgZ3JhZHVhdGlvbl95ZWFyX29yZGVyZWQgPSBmYWN0b3IoDQogICAgICBCOCwNCiAgICAgIGxldmVscyA9IGNvcnJlY3Rfb3JkZXIsDQogICAgICBvcmRlcmVkID0gVFJVRQ0KICAgICkNCiAgKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShFMTRfMSkpICU+JQ0KICBncm91cF9ieShncmFkdWF0aW9uX3llYXJfb3JkZXJlZCwgQjMpICU+JSAgIyBHcm91cCBieSB0aGUgb3JkZXJlZCBmYWN0b3INCiAgc3VtbWFyaXplKA0KICAgIG1lYW5fc2FsYXJ5ID0gbWVhbihFMTRfMSksDQogICAgc2UgPSBzZChFMTRfMSkgLyBzcXJ0KG4oKSksDQogICAgbG93ZXJfY2kgPSBtZWFuX3NhbGFyeSAtIDEuOTYgKiBzZSwNCiAgICB1cHBlcl9jaSA9IG1lYW5fc2FsYXJ5ICsgMS45NiAqIHNlLA0KICAgIC5ncm91cHMgPSAiZHJvcCIgICMgRXhwbGljaXRseSBkcm9wIGdyb3VwaW5nDQogICkgJT4lDQogIG11dGF0ZShzYWxhcnlfbGFiZWwgPSBwYXN0ZTAoZm9ybWF0KHJvdW5kKG1lYW5fc2FsYXJ5KSwgYmlnLm1hcmsgPSAiLCIpLCAiIEFNRCIpKQ0KDQpnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IGdyYWR1YXRpb25feWVhcl9vcmRlcmVkLCB5ID0gbWVhbl9zYWxhcnksIA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBCMywgZ3JvdXAgPSBCMykpICsNCiAgZ2VvbV9wb2ludHJhbmdlKGFlcyh5bWluID0gbG93ZXJfY2ksIHltYXggPSB1cHBlcl9jaSksDQogICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArDQogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKw0KICBnZW9tX3RleHQoYWVzKHkgPSB1cHBlcl9jaSwgbGFiZWwgPSBzYWxhcnlfbGFiZWwpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNSksDQogICAgICAgICAgICB2anVzdCA9IC0wLjUsIHNpemUgPSAzLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJNZWFuIFNhbGFyeSB3aXRoIDk1JSBDb25maWRlbmNlIEludGVydmFscyIsDQogICAgICAgeCA9ICJHcmFkdWF0aW9uIFllYXIiLCB5ID0gIk1lYW4gU2FsYXJ5IChBTUQpIiwNCiAgICAgICBjb2xvciA9ICJHZW5kZXIiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KTGV0J3MgYWxzbyBzZWUgdGhlIGNvdW50IG9mIG1lbiBhbmQgd29tZW4gYmFzZWQgb24gdGhlIGdyYWR1YXRpb24geWVhci4NCmBgYHtyfQ0KZ3JhZHVhdGlvbl9zdW1tYXJ5IDwtIGRlY29kZWRfZGF0YSAlPiUNCiAgZmlsdGVyKCFpcy5uYShCMyksICFpcy5uYShCOCkpICU+JQ0KICBjb3VudChHZW5kZXIgPSBCMywgR3JhZHVhdGlvbl9ZZWFyID0gQjgsIG5hbWUgPSAiQ291bnQiKSAlPiUNCg0KICBncm91cF9ieShHcmFkdWF0aW9uX1llYXIpICU+JQ0KICBtdXRhdGUoUGVyY2VudGFnZSA9IENvdW50IC8gc3VtKENvdW50KSAqIDEwMCkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgDQogIG11dGF0ZShQZXJjZW50YWdlX0xhYmVsID0gcGFzdGUwKHJvdW5kKFBlcmNlbnRhZ2UsIDEpLCAiJSIpKSAlPiUNCiAgDQogIHNlbGVjdChHZW5kZXIsIEdyYWR1YXRpb25fWWVhciwgQ291bnQsIFBlcmNlbnRhZ2UsIFBlcmNlbnRhZ2VfTGFiZWwpICU+JQ0KICBhcnJhbmdlKEdyYWR1YXRpb25fWWVhciwgR2VuZGVyKQ0KDQpwcmludChncmFkdWF0aW9uX3N1bW1hcnkpDQpgYGANCg0KRmluZGluZ3M6IEluIHRoaXMgY2hhcnQsIHdlIGhhdmUgY29uc2lkZXJlZCB0aGUgcmVjb3JkcyB3aGVyZSB0aGUgaW1wbGljaXQgc2FsYXJpZXMgYXJlIG1lbnRpb25lZC4NCldlIHNlZSB0aGF0IHRoZSBudW1iZXIgb2YgZmVtYWxlcyBpcyBiaWdnZXIgaGVyZS4gSG93ZXZlciwgdGhlIG1lYW4gc2FsYXJ5IG9mIHRoZSBtYWxlcyBpcyBzdGlsbCBoaWdoZXIsIHdpdGggYmlnZ2VyIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFzIGluIHRoZSBwcmV2aW91cyBjaGFydC4NCg0KICpDYW4gV2UgRmluZCB0aGUgTWVhbiBTYWxhcnkgYnkgV29yayBMb2NhdGlvbiBhbmQgR2VuZGVyKg0KYGBge3J9DQpkZWNvZGVkX2RhdGEgPC0gZGVjb2RlZF9kYXRhJT4lDQptdXRhdGUoDQogICAgSjNfMSA9IGNhc2Vfd2hlbigNCiAgICAgIEozXzEgPT0gMSB+ICJBcm1lbmlhIiwNCiAgICAgIEozXzEgPT0gMiB+ICJBYnJvYWQiLA0KICAgICAgSjNfMSA9PSAzIH4gIk5vIFBhaWQgSm9iIg0KICAgICAgDQogICAgKQ0KICApICU+JQ0KbXV0YXRlKA0KICAgIEozXzIgPSBjYXNlX3doZW4oDQogICAgICBKM18yID09IDEgfiAiQXJtZW5pYSIsDQogICAgICBKM18yID09IDIgfiAiQWJyb2FkIiwNCiAgICAgIEozXzIgPT0gMyB+ICJObyBQYWlkIEpvYiINCiAgICAgIA0KICAgICkNCiAgKQ0KDQp1bmlxdWUoY2xlYW5lZF9kYXRhWydKM18xJ10pDQp1bmlxdWUoZGVjb2RlZF9kYXRhWydKM18yJ10pDQpgYGANCkl0IGNvbWVzIG91dCB0aGF0IHdlIGNhbm5vdCB3b3JrIHdpdGggY29sdW1ucyBKM18xIGFuZCBKM18yLCB3aGljaCBzcGVjaWZ5IGlmIHRoZSBzdXJ2ZXkgdGFrZXIgd29ya3MgaW4gQXJtZW5pYS9hYnJvYWQvYm90aC9ubyBwYWlkIGpvYi4gVGhlIHJlYXNvbiBpcyB0aGF0IHdoZW4gY2xlYW5pbmcgdGhlIGRhdGEsIHdlIGtlcHQgb25seSB0aGUgcmVjb3JkcyB3aGVyZSBzYWxhcnkgcmFuZ2Ugb3IgZXhhY3Qgc2FsYXJ5IGlzIG1lbnRpb25lZC4NCg0KYGBge3J9DQpkZWNvZGVkX2RhdGEgPC0gZGVjb2RlZF9kYXRhJT4lDQogIG11dGF0ZSgNCiAgICBFMTAgPSBjYXNlX3doZW4oDQogICAgICBFMTAgPT0gMSB+ICJQdWJsaWMiLA0KICAgICAgRTEwID09IDIgfiAiTkdPIiwNCiAgICAgIEUxMCA9PSAzIH4gIlByaXZhdGUiLA0KICAgICAgRTEwID09IDQgfiAiU2VsZi1lbXBseWVkIg0KICAgICkNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIEY2ID0gY2FzZV93aGVuKA0KICAgICAgRjYgPT0gMSB+ICJQdWJsaWMiLA0KICAgICAgRjYgPT0gMiB+ICJOR08iLA0KICAgICAgRjYgPT0gMyB+ICJQcml2YXRlIiwNCiAgICAgIEY2ID09IDQgfiAiU2VsZi1lbXBsb3llZCINCiAgICApDQogICkNCmBgYA0KDQpMZXQncyBzZWUgaG93IG1hbnkgcmVjb3JkcyB3ZSBoYXZlIHdpdGggZmlsbGVkIHByaW1hcnkgam9iIGFuZCBzZWNvbmRhcnkgb25lcy4NCmBgYHtyfQ0KcHJpbWFyeV9qb2JfY291bnQgPC0gZGVjb2RlZF9kYXRhICU+JQ0KICBmaWx0ZXIoIWlzLm5hKEUxMCkpICU+JSAgDQogIGNvdW50KEIzLCBuYW1lID0gImNvdW50IikgIA0KcHJpbWFyeV9qb2JfY291bnQNCmBgYA0KDQpgYGB7cn0NCnNlY29uZGFyeV9qb2JfY291bnQgPC0gZGVjb2RlZF9kYXRhICU+JQ0KICBmaWx0ZXIoIWlzLm5hKEY2KSkgJT4lICANCiAgY291bnQoQjMsIG5hbWUgPSAiY291bnQiKQ0KDQpzZWNvbmRhcnlfam9iX2NvdW50DQpgYGANCg0KYGBge3J9DQpwbG90X2RhdGEgPC0gZGVjb2RlZF9kYXRhICU+JQ0KICBzZWxlY3QoZ2VuZGVyID0gQjMsIHNhbGFyeSA9IEUxNF8xLCBvd25lcnNoaXAgPSBFMTApICU+JSAgDQogIGZpbHRlcighaXMubmEoc2FsYXJ5KSwgIWlzLm5hKG93bmVyc2hpcCkpICU+JSAgICAgICAgICAgICAgDQogIG11dGF0ZShvd25lcnNoaXAgPSBmYWN0b3Iob3duZXJzaGlwKSkgDQoNCnN1bW1hcnlfc3RhdHMgPC0gcGxvdF9kYXRhICU+JQ0KICBncm91cF9ieShnZW5kZXIsIG93bmVyc2hpcCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtZWFuX3NhbGFyeSA9IG1lYW4oc2FsYXJ5KSwNCiAgICBzZSA9IHNkKHNhbGFyeSkgLyBzcXJ0KG4oKSksDQogICAgbG93ZXJfY2kgPSBtZWFuX3NhbGFyeSAtIDEuOTYgKiBzZSwNCiAgICB1cHBlcl9jaSA9IG1lYW5fc2FsYXJ5ICsgMS45NiAqIHNlLA0KICAgIG4gPSBuKCksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICU+JQ0KICBmaWx0ZXIobiA+PSAxMCkgDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3Qoc3VtbWFyeV9zdGF0cywgDQogICAgICAgYWVzKHggPSBvd25lcnNoaXAsIHkgPSBtZWFuX3NhbGFyeSwgZmlsbCA9IGdlbmRlcikpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHdpZHRoID0gMC43KSArDQogIGdlb21fZXJyb3JiYXIoDQogICAgYWVzKHltaW4gPSBsb3dlcl9jaSwgeW1heCA9IHVwcGVyX2NpKSwNCiAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwNCiAgICB3aWR0aCA9IDAuMiwNCiAgICBjb2xvciA9ICJibGFjayINCiAgKSArDQogIGdlb21fdGV4dCgNCiAgICBhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQobWVhbl9zYWxhcnkvMTAwMCwgMSksICJrIFxuKG49IiwgbiwgIikiKSwNCiAgICAgICAgeSA9IHVwcGVyX2NpKSwNCiAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwNCiAgICB2anVzdCA9IC0wLjUsDQogICAgc2l6ZSA9IDMNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTWVhbiBTYWxhcnkgKEFNRCkgYnkgQ29tcGFueSBPd25lcnNoaXAgKFByaW1hcnkgSm9iKSIsDQogICAgc3VidGl0bGUgPSAiRXJyb3IgYmFycyBzaG93IDk1JSBjb25maWRlbmNlIGludGVydmFscyIsDQogICAgeCA9ICJPd25lcnNoaXAgVHlwZSIsDQogICAgeSA9ICJNZWFuIFNhbGFyeSAoQU1EKSIsDQogICAgZmlsbCA9ICJHZW5kZXIiDQogICkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQpGaW5kaW5nczogSW4gdGhpcyBjaGFydCwgd2UgaGF2ZSBjb25zaWRlcmVkIHRoZSByZWNvcmRzIHdoZXJlIHRoZSBpbXBsaWNpdCBzYWxhcmllcyBhcmUgbWVudGlvbmVkLg0KQ29uY2VudHJhdGluZyBvbiB0aGUgY2hhcnQgYWJvdmUsIHdlIGNhbiBzZWUgdGhhdCBvbmx5IGZlbWFsZXMgYXJlIHJlY29yZGVkIGFzIHNlbGYtZW1wbG95ZWQgKGtlZXBpbmcgaW4gbWluZCB0aGF0IHRoZSBkYXRhIGlzIGZpbHRlcmVkIHRvIGtlZXAgb25seSByZWNvcmRzIHdpdGggbWVudGlvbmVkIHNhbGFyeSkuIFRoZSBhbmFseXNpcyBhbHNvIHNob3dzIHRoYXQgbWFsZXMgZWFybiBtb3JlIGluIE5HT3MsIFByaXZhdGUgYW5kIFB1YmxpYyBlbnRlcnByaXNlcywgYnV0IHRoZSBoaWdoZXN0IGRpZmZlcmVuY2UgaXMgaW4gUHJpdmF0ZSBjb21wYW5pZXMuIEFsdGhvdWdoIHRoZXJlIGFyZSBtb3JlIGZlbWFsZXMgd2hvIGFuc3dlcmVkIHRoZXNlIHF1ZXN0aW9ucyB0aGVuIG1hbGVzLCB0aGUgZGlmZmVyZW5jZSBzdGlsbCBleGlzdHMuDQoNCmBgYHtyfQ0KbWVhbl9zYWxhcnlfYnlfcmVnaW9uIDwtIGRlY29kZWRfZGF0YSAlPiUNCiAgc2VsZWN0KGdlbmRlciA9IEIzLCByZWdpb24gPSBBMywgc2FsYXJ5ID0gRTE0XzEpICU+JQ0KICBmaWx0ZXIoIWlzLm5hKHJlZ2lvbiksICFpcy5uYShnZW5kZXIpLCAhaXMubmEoc2FsYXJ5KSkgJT4lDQogIGdyb3VwX2J5KHJlZ2lvbiwgZ2VuZGVyKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fc2FsYXJ5ID0gbWVhbihzYWxhcnksIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBtZWRpYW5fc2FsYXJ5ID0gbWVkaWFuKHNhbGFyeSwgbmEucm0gPSBUUlVFKSwgDQogICAgICAgICAgICBtaW5fc2FsYXJ5ID0gbWluKHNhbGFyeSwgbmEucm0gPSBUUlVFKSwgDQogICAgICAgICAgICBtYXhfc2FsYXJ5ID0gbWF4KHNhbGFyeSwgbmEucm0gPSBUUlVFKSkNCiAgDQptZWFuX3NhbGFyeV9ieV9yZWdpb24NCmBgYA0KDQpgYGB7cn0NCmRpZmZlcmVuY2VfaW5fbWVhbl9zYWxhcnlfYnlfcmVnaW9uIDwtIG1lYW5fc2FsYXJ5X2J5X3JlZ2lvbiAlPiUNCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGdlbmRlciwgdmFsdWVzX2Zyb20gPSBtZWFuX3NhbGFyeSkgJT4lDQogIG11dGF0ZSh3YWdlX2dhcCA9IE1hbGUgLSBGZW1hbGUpICU+JQ0KICBzZWxlY3QocmVnaW9uLCB3YWdlX2dhcCkNCg0KZGlmZmVyZW5jZV9pbl9tZWFuX3NhbGFyeV9ieV9yZWdpb24NCmBgYA0KDQpgYGB7cn0NCmFybWVuaWFfbWFwIDwtIHN0X3JlYWQoImFybWVuaWEuanNvbiIpDQpgYGANCmBgYHtyfQ0KcmVnaW9uX25hbWVfbWFwIDwtIHRpYmJsZTo6dGliYmxlKA0KICBtYXBfbmFtZSA9IGMoIlRhdnVzaCIsICJMb3JpIiwgIlNoaXJhayIsICJHZWdoYXJrdW5payIsICJWYXlvdHMgRHpvciIsIA0KICAgICAgICAgICAgICAgIlN5dW5payIsICJBcmFyYXQiLCAiQXJhZ2F0c290biIsICJBcm1hdmlyIiwgIktvdGF5ayIsICJFcmV2YW4iKSwNCiAgcmVnaW9uID0gYygiVGF2dXNoIiwgIkxvcmkiLCAiU2hpcmFrIiwgIkdlZ2hhcmt1bmlrIiwgIlZheW9jIER6b3IiLA0KICAgICAgICAgICAgICJTeXVuaXEiLCAiQXJhcmF0IiwgIkFyYWdhdHNvdG4iLCAiQXJtYXZpciIsICJLb3RheXEiLCAiWWVyZXZhbiIpICAjIG1hdGNoIHlvdXIgZGF0YQ0KKQ0KDQphcm1lbmlhX21hcCA8LSBhcm1lbmlhX21hcCAlPiUNCiAgbGVmdF9qb2luKHJlZ2lvbl9uYW1lX21hcCwgYnkgPSBjKCJuYW1lIiA9ICJtYXBfbmFtZSIpKQ0KYGBgDQoNCg0KYGBge3J9DQp3YWdlX2dhcF9tYXAgPC0gYXJtZW5pYV9tYXAgJT4lDQogIGxlZnRfam9pbihkaWZmZXJlbmNlX2luX21lYW5fc2FsYXJ5X2J5X3JlZ2lvbiwgYnkgPSAicmVnaW9uIikNCg0KZ2dwbG90KHdhZ2VfZ2FwX21hcCkgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gd2FnZV9nYXApLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oDQogICAgY29sb3JzID0gYygibmF2eSIsICJza3libHVlIiwgInllbGxvdyIsICJvcmFuZ2UiLCAicmVkIiksDQogICAgbmEudmFsdWUgPSAiZ3JheTkwIiwNCiAgICBuYW1lID0gIldhZ2UgR2FwIChBTUQpIg0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJHZW5kZXIgV2FnZSBHYXAgYnkgUmVnaW9uIChBcm1lbmlhKSIsDQogICAgc3VidGl0bGUgPSAiRGlmZmVyZW5jZSBpbiBtZWFuIHNhbGFyeTogTWFsZSAtIEZlbWFsZSIsDQogICAgY2FwdGlvbiA9ICJEYXRhOiBZb3VyIFN1cnZleSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCmBgYHtyfQ0KcCA8LSBnZ3Bsb3Qod2FnZV9nYXBfbWFwKSArDQogIGdlb21fc2YoYWVzKGZpbGwgPSB3YWdlX2dhcCwgdGV4dCA9IHBhc3RlKCJSZWdpb246IiwgbmFtZSwgIjxicj5XYWdlIEdhcDoiLCB3YWdlX2dhcCkpKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikNCmBgYA0KRmluZGluZ3M6IEFzIHNob3duIGluIHRoZSBtYXAsIHRoZXJlIGlzIGEgd2FnZSBnYXAgaW4gYWxsIHJlZ2lvbnMgb2YgQXJtZW5pYSwgd2hpY2ggZmx1Y3R1YXRlcyByb3VnaGx5IGJldHdlZW4gNTAwMDAgYW5kIDI1MDAwIEFNRCwgd2l0aCB0aGUgc21hbGxlc3QgZ2FwIHByZXNlbnQgaW4gQXJhcmF0IGFuZCB0aGUgYmlnZ2VzdCBpbiBBcm1hdmlyLg0KDQpVcmJhbiB2cyBSdXJhbCBtZWFuIHNhbGFyaWVzDQoNCmBgYHtyfQ0KdXJiYW5fcnVyYWxfc2FsYXJ5IDwtIGRlY29kZWRfZGF0YSAlPiUNCiAgc2VsZWN0KHNldHRsZW1lbnQgPSBBNSwgZ2VuZGVyID0gQjMsIHNhbGFyeSA9IEUxNF8xKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShzZXR0bGVtZW50KSwgIWlzLm5hKGdlbmRlciksICFpcy5uYShzYWxhcnkpKSAlPiUNCiAgZ3JvdXBfYnkoc2V0dGxlbWVudCwgZ2VuZGVyKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fc2FsYXJ5ID0gbWVhbihzYWxhcnkpLCBtaW5fc2FsYXJ5ID0gbWluKHNhbGFyeSksIG1heF9zYWxhcnkgPSBtYXgoc2FsYXJ5KSkNCg0KdXJiYW5fcnVyYWxfc2FsYXJ5DQpgYGANCg0KDQpgYGB7cn0NCg0KZ2dwbG90KGRlY29kZWRfZGF0YSwgYWVzKHggPSBBNSwgeSA9IEUxNF8xLCBmaWxsID0gQTUpKSArDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG9yID0gInJlZCIsIG91dGxpZXIuYWxwaGEgPSAwLjMpICsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgNTAwMDAwKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkluY29tZSBEaXN0cmlidXRpb246IFVyYmFuIHZzIFJ1cmFsIiwNCiAgICB4ID0gIlNldHRsZW1lbnQgVHlwZSIsDQogICAgeSA9ICJTYWxhcnkgKEFNRCkiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJVcmJhbiIgPSAiIzY2YzJhNSIsICJSdXJhbCIgPSAiI2ZjOGQ2MiIpKQ0KYGBgDQpGaW5kaW5nczogVGhlIG1lYW4gc2FsYXJ5IGluIHVyYmFuIHNldHRsZW1lbnRzIGlzIGhpZ2hlciB0aGFuIGluIHJ1cmFsIHNldHRsZW1lbnRzLiBNb3Jlb3ZlciwgdGhlIHJhbmdlIG9mIHNhbGFyaWVzIGlzIG11Y2ggYmlnZ2VyIHRoYW4gdGhhdCBvZiB1cmJhbiBzYWxhcmllcy4gDQo=